package com.fi.common.command;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

import com.fi.common.exception.ExceptionUtils;
import com.fi.common.log.FiLog;


public class CmdRunner {
	private final  String TAG="CmdRunner";
	
    private static String mLdLibsPath=null;
    private static String suNAME = "fu";
    private static String suPATH=null;
	
    public int ROOTSTATUS_ALL_SUCCESS	=0;				
    public int ROOTSTATUS_TEMP_ERR	=1;					
    public int ROOTSTATUS_INSTALL_ERR	=2;

    public CmdRunner(){
    	init();
    }
    
    public void init(){
    	if(mLdLibsPath==null){
    		mLdLibsPath=getLdLibsPath();
    	}
    	if(suPATH==null){
    		suPATH=getSupath();
    	}
    }

    private String getLdLibsPath() {
        if(CmdRunner.mLdLibsPath==null){
        	echoLdLibsPath();
        }
        return CmdRunner.mLdLibsPath;
    }
    
	private String getSupath() {
		String strPath;
		if(new File("/system/xbin/" + suNAME).exists()) {
			strPath = "/system/xbin/"+ suNAME;
		}
		else if(new File("/system/bin/"+ suNAME).exists()) {
			strPath = "/system/bin/"+ suNAME;
		}
		else {
			strPath = null;
		}
		return strPath;
	}

    private void echoLdLibsPath() {
        try {
            Process shProc = Runtime.getRuntime().exec("sh");
            DataOutputStream dataOs = new DataOutputStream(shProc.getOutputStream());
            dataOs.writeBytes("echo $LD_LIBRARY_PATH\n");
            dataOs.writeBytes("exit\n");
            dataOs.flush();
            shProc.waitFor();
            DataInputStream is = new DataInputStream(shProc.getInputStream());
            DataInputStream es = new DataInputStream(shProc.getErrorStream());
            while(is.available() > 0) {
                if(CmdRunner.mLdLibsPath == null) {
                    CmdRunner.mLdLibsPath = is.readLine();
                    FiLog.appLogD(TAG, "get LD_LIBRARY_PATH(), stdout: " + CmdRunner.mLdLibsPath + "\n");
                }
                else {
                    FiLog.appLogD(TAG, "get LD_LIBRARY_PATH(), stdout: " + is.readLine() + "\n");
                }
            }
            while(es.available() > 0) {
                FiLog.appLogD(TAG, "get LD_LIBRARY_PATH(), stderr: " + es.readLine() + "\n");
            }

            FiLog.appLogD(TAG, "get LD_LIBRARY_PATH(), return: " + shProc.exitValue());
        }
        catch(Exception e) {
            FiLog.appLogW(TAG, "exception: " + e);
        }

        if(CmdRunner.mLdLibsPath == null) {
            CmdRunner.mLdLibsPath = "/vendor/lib:/system/lib";
            FiLog.appLogD(TAG, "get LD_LIBRARY_PATH(), set default: /vendor/lib:/system/lib");
        }
    }
    
    
    
    public CmdRet execCmd(String cmd) {
    	return execCmd(new String[]{cmd});
    }
    
    public CmdRet execCmd(String[] cmds) {
    	String logCmd="execute cmd : ";
    	for(String cmd : cmds){
    		logCmd+=cmd +"\n";
    	}
    	FiLog.appLogI(TAG, logCmd);
    	
    	CmdRet ret=execCmd2(CmdRunner.suPATH, cmds);
    	return ret;
    }


    
    
    
    private CmdRet execCmd2(String exePath, String[] cmds) {
        CmdRet cmdRet =null;
        Process suProc = null;
        if(CmdRunner.mLdLibsPath==null){
        	echoLdLibsPath();
        }
        try {
            suProc = Runtime.getRuntime().exec(exePath);
            if(cmds.length > 0) {
                DataOutputStream os = new DataOutputStream(suProc.getOutputStream());
                DataInputStream is =new DataInputStream(suProc.getInputStream());
                DataInputStream es =new DataInputStream(suProc.getErrorStream());

                //先export 基本的ld环境变量
                os.writeBytes("export LD_LIBRARY_PATH=" + CmdRunner.mLdLibsPath + "\n");
                int cmdLen = cmds.length;
                for(int i=0;i<cmds.length;i++){
            		os.writeBytes(cmds[i] + "\n");
                    os.flush();
                }
                os.writeBytes("\n ret=$? \n echo ret=...$ret... \n");//\n ret=$? \n echo ret=...$ret... \n
                os.writeBytes("exit\n");
                os.flush();
                suProc.waitFor();
                
                cmdRet =new CmdRet();
                cmdRet.setStdout(getStdInfo(is));
                cmdRet.setStderr(getStdInfo(es));
                int lastCmdret=parseLastCmdRet(cmdRet.getStdout());
                cmdRet.setLastCmdRet(lastCmdret);
                
            }
        }
        catch(Exception e) {
        	FiLog.appLogE(TAG,"execute the " +  exePath +"failed"+e.toString());
        	cmdRet.setCrash(true);
        } finally {
            if(suProc != null) {
				 suProc.destroy();
			 }
        }
        return cmdRet;
    }
    /**
     * 分析并取得最后一条指令的结果
     * 如果是崩溃的返回-1
     * */
    public int parseLastCmdRet(String stdout){
    	if(stdout==null){
    		return -1;
    	}
    	int leftIndex=stdout.indexOf("ret=...")+"ret=...".length();
    	int rightIndex=stdout.lastIndexOf("...");
    	String retStr=stdout.substring(leftIndex,rightIndex);
    	return Integer.valueOf(retStr);
    }
    
    
    public boolean  checkIdGroup(){
    	String idString = null;
    	execCmd(new String[]{"id"});
    	if(idString==null || idString.equals("")){
    		return false;
    	}
     	if(idString.contains("uid=0") && idString.contains("gid=0")){
    		return true;
    	}
    	return false;
    }
    
    public String getStdInfo(DataInputStream stream){
		if(stream==null){
			FiLog.appLogE(TAG, "read the std info error : the stream is null");
			return null;
		}
		String stdInfo="";
		BufferedReader steamReader = new BufferedReader(new InputStreamReader(stream));
		
		try {
			String line="";
	        while((line = steamReader.readLine()) != null) {
	        	stdInfo+=line.trim() + "\n";
	        }
		} catch (IOException e) {
			ExceptionUtils.Log(e);
		} finally{
			try {
				if(steamReader!=null){
					steamReader.close();
				}
			} catch (IOException e) {
				FiLog.appLogE(TAG, "getStdInfo close failed"+e);
			}
		}
		return stdInfo;
	}
    
}
